//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<tagtext.h>
///	@path	~/src/gui/text/
///	@date	2008/07/06
///	@desc	.

#pragma once

#include "xeres.h"

#include "lib/utilities/string.h"

#include "gui/IGuiComp.h"
#include "gui/IGuiForm.h"
#include "gui/shifter.h"
#include "gui/composite/composition.h"
#include "gui/style/style.h"
#include "gui/style/uniscribe.h"
#include "gui/image/IBitmap.h"
#include "gui/image/ImageResource.h"

namespace xeres {

	/*! 
		\class	TagTextBase
		\brief	Provide basic functions for tag text.
	*/
	class TagTextBase
	{
	public:

		// forward declaration
		class Line;
		class Tag;

		// Text style for tag text.
		class TextStyle
		{
		public:

			/// \ctor
			TextStyle( void );

			/// \ctor
			TextStyle( const TextStyle& rhs );

			/// \brief	Set to default style.
			void SetDefault( void );

			/// \brief	Comparison.
			bool operator == ( const TextStyle& rhs ) const;

		public:

			// Text style.

			// Text font.
			Ref<StyleFont>		m_font;

			// Text color.
			ARGB					m_textColor;
			// Shadow color.
			ARGB					m_shadowColor;

			// Underline text.
			bool					m_underline;
			// Strike out text.
			bool					m_strikeout;
			// Shine text (edge).
			bool					m_shine;
			// Shake text.
			bool					m_shake;

		};

		/// \brief	Tag base.
		class Tag
		{
		public:

			/// \ctor
			Tag( void );

			/// \dtor
			~Tag( void );

			/// \brief	Clear to reuse again.
			void Clear( void );

			/// \brief	Determine if tag is a text or icon.
			bool IsIcon( void ) const { return m_icon.IsValid(); }

			/// \brief	Determine if tag is a text or icon.
			bool IsText( void ) const { return m_icon.IsNull(); }

			/// \brie	Determine if tag is animated.
			bool IsAnimated( void ) const;

			/// \brief	Get start.
			size_t GetStart( void ) const { return m_start; }
			/// \brief	Get width.
			size_t GetWidth( void ) const { return m_width; }

			/// \brief	Get height.
			size_t GetHeight( void ) const { return m_height; }

			/// \name	Method For Text Manipulation.
			//@{

			/// \brief	Get text of tag.
			const WString& GetText( void ) const { return m_text; }

			/// \brief	Set text of tag (Notice if icon is valid, it will cause an fatal to stop overwrite).
			void SetText( const WString& text );

			/// \brief	Split text to next line.
			void SplitText( size_t limit , Tag * next );

			/// \brief	Join text with next line.
			void JoinText( size_t rest , Tag * next );

			//@}

			/// \name	Method For Icon Manipulation.
			//@{

			/// \brief	Get icon of tag.
			RefWeak<IBitmap> GetIcon( void ) const { return m_icon; }

			/// \brief	Set icon of tag (Notice if text is not empty, it will cause an fatal to stop overwrite).
			void SetIcon( RefWeak<IBitmap> icon );

			/// \brief	Is tickable.
			bool IsTickable( void );

			//@}

			/// \name	Presents tag.
			//@{

			/// \brief	Tick update.
			void Tick( Updater& updater , float dTime , Rect<int>& region );

			/// \brief	Draw XGUI component to composition.
			void Draw( Composition& composition , const Rect<int>& bound );

			//@}

		public:

			//@ data

			// Previous & next tag.
			Tag *					m_prev;
			Tag *					m_next;

			// Line that tag inside.
			Line *					m_line;

			// Basic attributes.
			ushort					m_start;
			ushort					m_width;
			ushort					m_height;
			short					m_frameIndex;

			// Text string.
			WString					m_text;
			TextStyle				m_style;

			// Icon or sprite animation.
			Ref<IBitmap>			m_icon;

			// Animation status.
			float					m_time;
		};

		/// \brief	Encapsulates a tag text line.
		class Line
		{
		public:

			/// \ctor
			Line( void );

			/// \ctor
			Line( const Line& rhs );

			/// \brief	New line.
			void NewLine( void );

			/// \brief	Determine if line is empty.
			bool IsEmpty( void ) const { return m_leading == NULL || m_ending == NULL; }

			/// \brief	Get height of line.
			size_t GetHeight( void ) const { return m_height; }

			/// \brief	Get width of line.
			size_t GetWdith( void ) const { return m_width; }

			/// \brief	Append tag to line.
			void AppendTag( Tag * tag , Pair<int>& pos );

			/// \brief	Complete a line.
			void CompleteLine( void );

			/// \name	Presents line.
			//@{

			/// \brief	Tick update.
			void Tick( Updater& updater , float dTime , Rect<int>& region );

			/// \brief	Draw XGUI component to composition.
			void Draw( Composition& composition , const Rect<int>& bound );

			//@}

		public:

			//@ data

			// leading & ending of line
			Tag *			m_leading;
			Tag *			m_ending;

			// line info.
			size_t			m_base;
			size_t			m_height;
			size_t			m_width;
			size_t			m_descent;
		};

	protected:

		// Allocate new tag.
		static Tag * AllocTag( void );

		// Free unused tag.
		static void FreeTag( Tag * tag );

	};

} // namespace xeres
